﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Text;
using DomainDriver.DomainModeling.DomainObjects;
using DomainDriver.DomainModeling.Queries;
using DomainDriver.DomainModeling.StorageManagers.DataSetStorage;
using DomainDriver.DomainModeling.StorageManagers.EntityFrameworkStorage;
using AutomotivePricingModel.ValueObjects.YearlyFinancialAssessments;
using ObjectRow = AutomotivePricingModel.AutomotivePricingDataSet.CompaniesRow;
using NestedObjectRow = AutomotivePricingModel.AutomotivePricingDataSet.YearlyFinancialAssessmentsRow;

namespace AutomotivePricingModel.Companies
{
    public partial class Company : IEfEntity<Guid>, IEfAggregateRoot<Company>, IDataSetSerializable<AutomotivePricingDataSet, DataRow>
    {
        #region ADO .NET Entities Framework Storage

        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public Guid EF_Key
        {
            get { return m_Key; }
            set { m_Key = value; }
        }

        [Required]
        [Association("Assc_Company_YearlyFinancialAssessment", "EF_EarningsHistoryId", "EF_YearlyFinancialAssessmentId")]
        [ForeignKey("EF_EarningsHistory")]
        public Nullable<Guid> EF_EarningsHistoryId
        {
            get { return m_EarningsHistoryId; }
            set { m_EarningsHistoryId = value; }
        }

        [Required]
        public YearlyFinancialAssessment EF_EarningsHistory
        {
            get
            {
                if (!m_EarningsHistoryId.HasValue)
                { return null; }
                if (!m_EarningsHistory.Key.Equals(m_EarningsHistoryId.Value))
                { return null; }
                return m_EarningsHistory;
            }
            set
            {
                if (!m_EarningsHistoryId.HasValue)
                { throw new ApplicationException(); }
                if (m_EarningsHistoryId.Value != value.Key)
                { throw new ApplicationException(); }
                m_EarningsHistory = value;
            }
        }

        ICollection<QuerySpecification> IEfAggregateRoot<Company>.OverriddenQueries
        {
            get { return new List<QuerySpecification>(); }
        }

        bool IEfAggregateRoot<Company>.SearchNestedAggregateValues(DbContext context, IParameterizedQuery<Company> query)
        {
            throw new NotImplementedException();
        }

        void IEfAggregateRoot<Company>.ReadNestedAggregateValues(DbContext context)
        {
            YearlyFinancialAssessment assessment = YearlyFinancialAssessment.ReadValueObject(context, this.m_EarningsHistoryId.Value);
            this.m_EarningsHistory = assessment;
        }

        void IEfAggregateRoot<Company>.AddNestedAggregateValues(DbContext context)
        {
            YearlyFinancialAssessment.AddValueObject(context, this.m_EarningsHistory);
        }

        void IEfAggregateRoot<Company>.UpdateNestedAggregateValues(DbContext context, Company originalAggregateRoot)
        {
            YearlyFinancialAssessment.UpdateValueObject(context, this.m_EarningsHistory, originalAggregateRoot.m_EarningsHistory);
        }

        void IEfAggregateRoot<Company>.DeleteNestedAggregateValues(DbContext context)
        {
            YearlyFinancialAssessment.DeleteValueObject(context, this.m_EarningsHistory);
        }

        #endregion

        #region AutomotivePricingDataSet Serialization

        string IDataSetSerializable<AutomotivePricingDataSet, DataRow>.ObjectTableName
        {
            get { return AutomotivePricingDataSet.SchemaHelper.Companies.TableName; }
        }

        string IDataSetSerializable<AutomotivePricingDataSet, DataRow>.KeyColumnName
        {
            get { return AutomotivePricingDataSet.SchemaHelper.Companies.EF_CompanyIdColumn.ColumnName; }
        }

        void IDataSetSerializable<AutomotivePricingDataSet, DataRow>.Serialize(AutomotivePricingDataSet datasource, DataRow dataRow)
        {
            ObjectRow objectRecord = dataRow as ObjectRow;

            objectRecord.EF_CompanyId = m_Key;
            objectRecord.CeoName = m_CeoName;
            objectRecord.CompanyName = m_CompanyName;
            objectRecord.FounderName = m_FounderName;
            DataSetSerializationUtilities.SerializeNullableField<DateTime>(m_CompanyFoundingDate, objectRecord, AutomotivePricingDataSet.SchemaHelper.Companies.CompanyFoundingDateColumn);
            DataSetSerializationUtilities.SerializeNullableField<Guid>(m_CountryOfHeadquarters, objectRecord, AutomotivePricingDataSet.SchemaHelper.Companies.CountryOfHeadquartersColumn);
            // LATER: Try to make m_EarningsHistoryId non-nullable since vale generated from DB was non-null
            DataSetSerializationUtilities.SerializeNullableField<Guid>(m_EarningsHistoryId, objectRecord, AutomotivePricingDataSet.SchemaHelper.Companies.EF_EarningsHistoryIdColumn);

            NestedObjectRow nestedObjectRow = datasource.YearlyFinancialAssessments.NewYearlyFinancialAssessmentsRow();
            m_EarningsHistory.Serialize(datasource, nestedObjectRow);
        }

        void IDataSetSerializable<AutomotivePricingDataSet, DataRow>.Deserialize(AutomotivePricingDataSet datasource, DataRow dataRow)
        {
            ObjectRow objectRecord = dataRow as ObjectRow;

            m_Key = objectRecord.EF_CompanyId;
            m_CeoName = objectRecord.CeoName;
            m_CompanyName = objectRecord.CompanyName;
            m_FounderName = objectRecord.FounderName;

            DataSetSerializationUtilities.DeserializeNullableField<DateTime>(out m_CompanyFoundingDate, objectRecord, AutomotivePricingDataSet.SchemaHelper.Companies.CompanyFoundingDateColumn);
            DataSetSerializationUtilities.DeserializeNullableField<Guid>(out m_CountryOfHeadquarters, objectRecord, AutomotivePricingDataSet.SchemaHelper.Companies.CountryOfHeadquartersColumn);
            DataSetSerializationUtilities.DeserializeNullableField<Guid>(out m_EarningsHistoryId, objectRecord, AutomotivePricingDataSet.SchemaHelper.Companies.EF_EarningsHistoryIdColumn);

            m_EarningsHistory.Deserialize(datasource, objectRecord.YearlyFinancialAssessmentsRow);
        }

        #endregion
    }
}